﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using OBID;

namespace SSS.RFIDWrapper
{
    public class RFIDReadWrapper : FeIscListener
    {
        byte[] CustomerIDArray = new byte[4];

        FedmIscReader fedm;
        string TransponderSerialNumber;
        byte SerialNumberLen;
        uint persistenceResetTime = 0;

        Thread MyThread;
        Boolean Prepared = false;
        public bool running;

        //declaration from delegatetyp
        public delegate void DelegateTagChanged(string[] serialNumber, byte[] tagType);
        public delegate void DelegateLastError(string err);
        public delegate void DelegateNoTag(int readerStatus);
        public delegate void DelegateOnSendProtocol(string sendprotocol);
        public delegate void DelegateOnReceiveProtocol(string receiveprotocol);

        public string GetReaderID()
        {
            try
            {
                return fedm.GetPortPara("Device-ID");
            }
            catch
            {
                return "";
            }
        }

        public string GetCustomerID()
        {
            CustomerIDArray = new byte[4];
            Prepared = false;
            running = true;

            while (running || !Prepared)
            {
                Application.DoEvents();
            }
            if (Read())
                return RFIDHelperclass.ByteArrayToString(CustomerIDArray);
            else
                return null;
        }

        public Boolean InitializeReader()
        {
            MyThread = new Thread(new ThreadStart(DetectThread));

            //USB port Connecten
            try
            {
                fedm = new FedmIscReader();
                fedm.ConnectUSB(0);
                fedm.SetTableSize(FedmIscReaderConst.ISO_TABLE, 128);
            }
            catch (FePortDriverException ex)
            {
                return false;
                //MessageBox.Show(ex.ToString(), "Error");
            }

            if (fedm.Connected == true)
            {
                //Liest die gesamte Leserkonfiguration aus.
                try
                {
                    fedm.ReadCompleteConfiguration(false);
                }
                catch (Exception ex)
                {
                    fedm.DisConnect();
                    return false;
                    //MessageBox.Show(ex.ToString(), "Error");
                }

                // set Persistence Reset Time in Reader Configuration to zero
                // this speeds up inventory cycles
                int back = OBID.Fedm.ERROR_UNSUPPORTED_NAMESPACE;

                //Testet ob ein Parametername vom  eingestellten Lesertyp unterstützt wird
                try
                {
                    back = fedm.TestConfigPara(OBID.ReaderConfig.Transponder.PersistenceReset.Antenna.No1.PersistenceResetTime);
                }
                catch (Exception ex)
                {
                    // ignore Exception
                }

                // if reader supports this parameter, set it !
                if (0 == back)
                {
                    try
                    {
                        back = fedm.GetConfigPara(OBID.ReaderConfig.Transponder.PersistenceReset.Antenna.No1.PersistenceResetTime, out persistenceResetTime, false);
                        back = fedm.SetConfigPara(OBID.ReaderConfig.Transponder.PersistenceReset.Antenna.No1.PersistenceResetTime, (uint)0, false);
                        if (back == 1) // return value 1 indicates modified parameter
                            back = fedm.ApplyConfiguration(false);
                    }
                    catch (Exception ex)
                    {
                        return false;
                        //MessageBox.Show(ex.ToString());
                    }
                }
            }


            if (fedm.Connected == true)
            {
                //Registry from Events send and receive
                fedm.AddEventListener(this, FeIscListenerConst.SEND_STRING_EVENT);
                fedm.AddEventListener(this, FeIscListenerConst.RECEIVE_STRING_EVENT);

                //Thread starten in Background
                running = false;
                MyThread.IsBackground = true;
                MyThread.Start();
            }
            else
            {
                MessageBox.Show("Not Connected");
                return false;
            }

            return true;
        }

        //Construktor, Reader Verbinden, Eventhandler, Threat
        public RFIDReadWrapper()
        {
            InitializeReader();
        }

        private Boolean PrepareTransponder()
        {
            int selRow;
            int mode;
            byte bTagType;

            selRow = 0;
            // get Tag Type
            fedm.GetTableData(selRow, FedmIscReaderConst.ISO_TABLE, FedmIscReaderConst.DATA_TRTYPE, out bTagType);

            mode = Konstanten.mode;

            //seriennumemr haben wir bereits als globale variable
            SerialNumberLen = Convert.ToByte(TransponderSerialNumber.Length / 2);
            try
            {
                fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_REQ_UID, TransponderSerialNumber); // prepare for 0xB0 command
                if (bTagType == FedmIscReaderConst.TR_TYPE_ISO14443A ||
                bTagType == FedmIscReaderConst.TR_TYPE_ISO14443B)
                {
                    fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B2_REQ_UID, TransponderSerialNumber); // prepare for 0xB2 command
                }
            }
            catch (System.Exception ex)
            {
                //MessageBox.Show(ex.ToString(), "Error");
                return false;
            }
            return true;
        }


        /**************************************END************************************************/

        #region Methode from interface FeIscListener
        /*********************************Methode from interface FeIscListener**********************************************/

        public void OnReceiveProtocol(FedmIscReader reader, byte[] receiveProtocol)
        {
        }

        public void OnReceiveProtocol(FedmIscReader reader, String receiveProtocol)
        {
        }

        public void OnSendProtocol(FedmIscReader reader, byte[] sendProtocol)
        {
        }

        public void OnSendProtocol(FedmIscReader reader, String sendProtocol)
        {
        }

        /************************************************************END********************************************************/

        #endregion
        /*******************Methode to show asynchrone Result in GUI****************/

        //Show message error                                                      
        public void LastError(string err)
        {
            //this.buttonRun.Text = "R&un";
            MessageBox.Show(err, "Error");
        }

        //Clear tag list
        public void ClearList(int readerStatus)
        {
            this.TransponderSerialNumber = "0000";
        }

        //Show multiple TranspondersID                                           
        public void TagChanged(string[] serialNumber, byte[] tagType)
        {
            if (running)
            {
                if (serialNumber.Length > 1)
                {
                    this.TransponderSerialNumber = "0000";
                }
                else
                {
                    //Ausreichend da nur eine seriennumer - Prüfe ob wirklich in 0
                    this.TransponderSerialNumber = serialNumber[0];
                    running = false;
                    if (PrepareTransponder())
                    {
                        Prepared = true;
                    }
                    else
                    {
                        running = true;
                    }
                }
            }
        }

        /****************************************END*********************************/

        // methode to execute the thread 
        private void DetectThread()
        {
            int readerStatus = 0;
            string[] serialNumber;
            byte[] tagType;

            //declaration from delegateobject 
            DelegateTagChanged TagChangedMethod = new DelegateTagChanged(TagChanged);
            DelegateLastError LastErrorMethod = new DelegateLastError(LastError);
            DelegateNoTag NoTagMethod = new DelegateNoTag(ClearList);

            object[] obj1 = new object[2];

            while (true)
            {
                if (running == true)
                {
                    fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_CMD, 0x01);
                    fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_MODE, 0x00);
                    try
                    {
                        fedm.ResetTable(FedmIscReaderConst.ISO_TABLE);
                        fedm.SendProtocol(0x69); // RFReset
                        readerStatus = fedm.SendProtocol(0xB0); // ISOCmd
                        if (readerStatus != 0 && readerStatus != 0x94)
                        {
                            NoTagMethod(readerStatus);
                            continue;
                        }

                        while (fedm.GetLastStatus() == 0x94) // more flag set?
                        {
                            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_MODE_MORE, 0x01);
                            fedm.SendProtocol(0xB0);
                        }
                        //new dimensiion from array serialNumber,tagtype,SeNumbLength
                        serialNumber = new string[fedm.GetTableLength(FedmIscReaderConst.ISO_TABLE)];
                        tagType = new byte[fedm.GetTableLength(FedmIscReaderConst.ISO_TABLE)];

                        if (fedm.GetTableLength(FedmIscReaderConst.ISO_TABLE) <= 0)
                            continue;

                        int i;
                        for (i = 0; i < fedm.GetTableLength(FedmIscReaderConst.ISO_TABLE); i++)
                        {
                            fedm.GetTableData(i, FedmIscReaderConst.ISO_TABLE, FedmIscReaderConst.DATA_SNR, out serialNumber[i]);
                            fedm.GetTableData(i, FedmIscReaderConst.ISO_TABLE, FedmIscReaderConst.DATA_TRTYPE, out tagType[i]);
                            // check, wether UHF tags are available in list
                        }
                        TagChangedMethod(serialNumber, null);
                    }
                    catch (Exception ex)
                    {
                        LastErrorMethod(ex.ToString());
                        running = false;
                    }
                }
            }
        }


        public void StopReader()
        {
            // stop reading
            running = false;
            Prepared = true;

            //remove Events 
            fedm.RemoveEventListener(this, FeIscListenerConst.SEND_STRING_EVENT);
            fedm.RemoveEventListener(this, FeIscListenerConst.RECEIVE_STRING_EVENT);

            if (fedm.Connected == true)
            {
                // set Persistence Reset Time in Reader Configuration back to old value
                int back = OBID.Fedm.ERROR_UNSUPPORTED_NAMESPACE;
                try
                {
                    back = fedm.TestConfigPara(OBID.ReaderConfig.Transponder.PersistenceReset.Antenna.No1.PersistenceResetTime);
                }
                catch (Exception ex)
                { // ignore Exception
                }
                // if reader supports this parameter, set it back to old value !
                if (0 == back)
                {
                    try
                    {
                        back = fedm.SetConfigPara(OBID.ReaderConfig.Transponder.PersistenceReset.Antenna.No1.PersistenceResetTime, persistenceResetTime, false);
                        if (back == 1) // return value 1 indicates modified parameter
                            back = fedm.ApplyConfiguration(false);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.ToString(), "Error");
                    }
                }
                fedm.DisConnect();
            }
        }

        #region Methode to show protocol
        /******************** Methode to show protocol*****************************/

        //show sent Protocol
        public void DisplaySendProtocol(string protocol)
        {
        }

        //show received protocol
        public void DisplayReceiveProtocol(string protocol)
        {
        }

        /********************************END****************************************/

        #endregion




        /*### 
         * Wenn Transponder-Suche gestoppt kann gelesen werden
         * 
         */
        private Boolean Read()
        {
            byte[] data;
            byte blockSize;
            int idx;
            int dbn;
            int address;
            int mode;

            long datalocation = FedmIscReaderConst.DATA_RxDB;

            //   mode = 1;  Addressed Mode
            mode = Konstanten.mode;

            // set IscTable-Parameter
            dbn = Konstanten.dbn; //Anzahl zu lesender Blöcke
            address = Konstanten.address; //Startblock, bei dem begonnen wird zu lesen

            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_MODE, (byte)0);
            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_REQ_UID, TransponderSerialNumber);
            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_CMD, 0x23);
            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_REQ_DBN, dbn);
            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_MODE_ADR, mode);
            fedm.SetData(FedmIscReaderID.FEDM_ISC_TMP_B0_REQ_DB_ADR, address);

            // Send ReadMultipleBlocks-Protocol - "Ausführen"
            try
            {
                fedm.SendProtocol(0xB0);
            }

            catch (System.Exception ex)
            {
                //MessageBox.Show(ex.ToString(), "Error");
                return false;
            }

            // idx  wegen Mode = 1 (Addressed)
            idx = fedm.FindTableIndex(0, FedmIscReaderConst.ISO_TABLE, FedmIscReaderConst.DATA_SNR, TransponderSerialNumber);

            // get blockSize from ISC-table, default = 4
            FedmIsoTableItem item;
            try
            {
                item = (FedmIsoTableItem)fedm.GetTableItem(idx, FedmIscReaderConst.ISO_TABLE);
                //Blocksize des Transponders auslesen
                item.GetData((FedmIscReaderConst.DATA_BLOCK_SIZE), out blockSize);
            }
            catch (System.Exception ex)
            {
                //MessageBox.Show(ex.ToString(), "Error");
                return false;
            }

            // Default-Wert für blockSize nehmen.
            if (blockSize == 0)
            {
                blockSize = 4; // default value
            }

            //Set DataBlockData from ResponseBuffer to Array
            for (int i = 0; i < dbn; i++)
            {
                //data=byte[0]
                item.GetData(datalocation, address + i, out data);
                //data in Array
                CustomerIDArray = data;
            }
            return true;
        }
    }
}
